home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / pgppubring.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  14KB  |  788 lines

  1. /*
  2.  * Copyright (C) 1997 Thomas Roessler <roessler@guug.de>
  3.  * 
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  * 
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  * 
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */ 
  18.  
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <unistd.h>
  24. #include <time.h>
  25.  
  26. #include "sha.h"
  27.  
  28. #include "mutt.h"
  29. #include "pgp.h"
  30.  
  31. #define CHUNKSIZE 1024
  32.  
  33. static unsigned char *pbuf = NULL;
  34. static size_t plen = 0;
  35.  
  36. enum packet_tags {
  37.   PT_RES0 = 0,        /* reserved */
  38.   PT_ESK,        /* Encrypted Session Key */
  39.   PT_SIG,        /* Signature Packet */
  40.   PT_CESK,        /* Conventionally Encrypted Session Key Packet */
  41.   PT_OPS,        /* One-Pass Signature Packet */
  42.   PT_SECKEY,        /* Secret Key Packet */
  43.   PT_PUBKEY,        /* Public Key Packet */
  44.   PT_SUBSECKEY,        /* Secret Subkey Packet */
  45.   PT_COMPRESSED,    /* Compressed Data Packet */
  46.   PT_SKE,        /* Symmetrically Encrypted Data Packet */
  47.   PT_MARKER,        /* Marker Packet */
  48.   PT_LITERAL,        /* Literal Data Packet */
  49.   PT_TRUST,        /* Trust Packet */
  50.   PT_NAME,        /* Name Packet */
  51.   PT_SUBKEY,        /* Subkey Packet */
  52.   PT_RES15,        /* Reserved */
  53.   PT_COMMENT        /* Comment Packet */
  54. };
  55.  
  56. const char *pgp_packet_name[] = {
  57.   "reserved",
  58.   "Encrypted Session Key",
  59.   "Signature Packet",
  60.   "Conventionally Encrypted Session Key Packet",
  61.   "One-Pass Signature Packet",
  62.   "Secret Key Packet",
  63.   "Public Key Packet",
  64.   "Secret Subkey Packet",
  65.   "Compressed Data Packet",
  66.   "Symmetrically Encrypted Data Packet",
  67.   "Marker Packet",
  68.   "Literal Data Packet",
  69.   "Trust Packet",
  70.   "Name Packet",
  71.   "Subkey Packet",
  72.   "Reserved",
  73.   "Comment Packet"
  74. };
  75.  
  76. static const char *pkalgbytype(unsigned char type)
  77. {
  78.   switch(type)
  79.   {
  80.     case 1: return "RSA";
  81.     case 2: return "RSA";
  82.     case 3: return "RSA";
  83.     case 16: return "ElG";
  84.     case 17: return "DSA";
  85.     default: return "unk";
  86.   }
  87. }
  88.  
  89. /* unused */
  90.  
  91. #if 0
  92.  
  93. static const char *hashalgbytype(unsigned char type)
  94. {
  95.   switch(type)
  96.   {
  97.     case 1: return "MD5";
  98.     case 2: return "SHA1";
  99.     case 3: return "RIPE-MD/160";
  100.     case 4: return "HAVAL";
  101.     default: return "unknown";
  102.   }
  103. }
  104.  
  105. #endif
  106.  
  107. static short canencrypt(unsigned char type)
  108. {
  109.   switch(type)
  110.   {
  111.     case 1:
  112.     case 2:
  113.     case 16:
  114.         return 1;
  115.     default:
  116.         return 0;
  117.   }
  118. }
  119.  
  120. static short cansign(unsigned char type)
  121. {
  122.   switch(type)
  123.   {
  124.     case 1:
  125.     case 3:
  126.     case 17:
  127.         return 1;
  128.     default:
  129.         return 0;
  130.   }
  131. }
  132.  
  133. /* return values: 
  134.  *
  135.  * 1 = sign only
  136.  * 2 = encrypt only
  137.  * 3 = both
  138.  */
  139.  
  140. static short get_abilities(unsigned char type)
  141. {
  142.   return (canencrypt(type) << 1) | cansign(type);
  143. }
  144.  
  145. static int read_material(size_t material, size_t *used, FILE *fp)
  146. {
  147.   if(*used + material >= plen)
  148.   {
  149.     unsigned char *p;
  150.     size_t nplen;
  151.     
  152.     nplen = *used + material + CHUNKSIZE;
  153.  
  154.     if(!(p = realloc(pbuf, nplen)))
  155.     {
  156.       mutt_perror("realloc");
  157.       return -1;
  158.     }
  159.     plen = nplen;
  160.     pbuf = p;
  161.   }
  162.       
  163.   if(fread(pbuf + *used, 1, material, fp) < material)
  164.   {
  165.     mutt_perror("fread");
  166.     return -1;
  167.   }
  168.   
  169.   *used += material;
  170.   return 0;
  171. }
  172.  
  173. static unsigned char *pgp_read_packet(FILE *fp, size_t *len)
  174. {
  175.   size_t used = 0;
  176.   long startpos;
  177.   unsigned char ctb;
  178.   unsigned char b;
  179.   size_t material;
  180.   
  181.   startpos = ftell(fp);
  182.   
  183.   if(!plen)
  184.   {
  185.     plen = CHUNKSIZE;
  186.     pbuf = safe_malloc(plen);
  187.   }
  188.  
  189.   if(fread(&ctb, 1, 1, fp) < 1)
  190.   {
  191.     if(!feof(fp))
  192.        mutt_perror("fread"); 
  193.     goto bail;
  194.   }
  195.  
  196.   if(!(ctb & 0x80))
  197.   {
  198.     goto bail;
  199.   }
  200.  
  201.   if(ctb & 0x40)    /* handle PGP 5.0 packets. */
  202.   {
  203.     int partial = 0;
  204.     pbuf[0] = ctb; used++;
  205.     
  206.     do {
  207.       if(fread(&b, 1, 1, fp) < 1)
  208.       {
  209.     mutt_perror("fread");
  210.     goto bail;
  211.       }
  212.       
  213.       if(b < 192)
  214.       {
  215.     material = b;
  216.     partial = 0;
  217.     material -= 1;
  218.       } 
  219.       else if(192 <= b && b <= 223)
  220.       {
  221.     material = (b - 192) * 256;
  222.     if(fread(&b, 1, 1, fp) < 1)
  223.     {
  224.       mutt_perror("fread");
  225.       goto bail;
  226.     }
  227.     material += b + 192;
  228.     partial = 0;
  229.     material -= 2;
  230.       }
  231.       else
  232.       {
  233.     material = 1 << (b & 0x1f);
  234.     partial = 1;
  235.     material -= 1;
  236.       }
  237.     
  238.       if(read_material(material, &used, fp) == -1)
  239.     goto bail;
  240.  
  241.     } while (partial);
  242.   }
  243.   else        /* Old-Style PGP */
  244.   {
  245.     int bytes = 0;
  246.     pbuf[0] = 0x80 | ((ctb >> 2) & 0x0f);
  247.     used++;
  248.     
  249.     switch(ctb & 0x03)
  250.     {
  251.       case 0:
  252.       {
  253.         if(fread(&b, 1, 1, fp) < 1)
  254.     {
  255.       mutt_perror("fread");
  256.       goto bail;
  257.     }
  258.     
  259.     material = b;
  260.     break;
  261.       }
  262.     
  263.       case 1:
  264.           bytes = 2;
  265.       
  266.       case 2:
  267.       {
  268.     int i;
  269.  
  270.     if(!bytes) bytes = 4;
  271.     
  272.     material = 0;
  273.     
  274.     for(i = 0; i < bytes; i++)
  275.     {
  276.       if(fread(&b, 1, 1, fp) < 1)
  277.       {
  278.         mutt_perror("fread");
  279.         goto bail;
  280.       }
  281.       
  282.       material = (material << 8) + b;
  283.     }
  284.     break;
  285.       }
  286.       
  287.       default:
  288.         goto bail;
  289.     }
  290.     
  291.     if(read_material(material, &used, fp) == -1)
  292.       goto bail;
  293.   }
  294.   
  295.   if(len)
  296.     *len = used;
  297.   
  298.   return pbuf;
  299.   
  300.   bail:
  301.   
  302.   fseek(fp, startpos, SEEK_SET);
  303.   return NULL;
  304. }
  305.  
  306. static KEYINFO *pgp_new_keyinfo(void)
  307. {
  308.   KEYINFO *p;
  309.  
  310.   p = safe_malloc(sizeof(KEYINFO));
  311.   p->keyid = NULL;
  312.   p->address = NULL;
  313.   p->flags = 0;
  314.   p->next = NULL;
  315.   p->keylen = 0;
  316.  
  317.   return p;
  318. }
  319.  
  320. static KEYINFO *pgp_parse_pgp2_key(unsigned char *buff, size_t l)
  321. {
  322.   KEYINFO *p;
  323.   unsigned char alg;
  324.   size_t expl;
  325.   long id;
  326.   unsigned long gen_time = 0;
  327.   unsigned short exp_days = 0;
  328.   size_t j;
  329.   int i, k;
  330.   unsigned char scratch[LONG_STRING];
  331.   
  332.   if(l < 12)
  333.     return NULL;
  334.   
  335.   p = pgp_new_keyinfo();
  336.   
  337.   for(i = 0, j = 2; i < 4; i++)
  338.     gen_time = (gen_time << 8) + buff[j++];
  339.   
  340.   for(i = 0; i < 2; i++)
  341.     exp_days = (exp_days << 8) + buff[j++];
  342.   
  343.   if(exp_days && time(NULL) > gen_time + exp_days * 24 * 3600)
  344.     p->flags |= KEYFLAG_EXPIRED;
  345.   
  346.   alg = buff[j++];
  347.       
  348.   p->algorithm = pkalgbytype(alg);
  349.   p->flags |= get_abilities(alg);
  350.   
  351.   expl = 0;
  352.   for(i = 0; i < 2; i++)
  353.     expl = (expl << 8) + buff[j++];
  354.   
  355.   p->keylen = expl;
  356.   
  357.   expl = (expl + 7)/ 8;
  358.   if(expl < 4)
  359.     goto bailout;
  360.  
  361.   
  362.   j += expl - 8;
  363.   
  364.   for(k = 0; k < 2; k++)
  365.   {
  366.     for(id = 0, i = 0; i < 4; i++)
  367.       id = (id << 8) + buff[j++];
  368.     
  369.     snprintf((char *)scratch + k * 8, sizeof(scratch) - k * 8, 
  370.          "%08lX", id);
  371.   }
  372.   
  373.   p->keyid = safe_strdup((char *)scratch);
  374.   
  375.   return p;
  376.   
  377.   bailout:
  378.   
  379.   safe_free((void **)&p);
  380.   return NULL;
  381. }
  382.  
  383. static void pgp_make_pgp3_fingerprint(unsigned char *buff, size_t l,
  384.                       unsigned char *digest)
  385. {
  386.   unsigned char dummy;
  387.   SHA_CTX context;
  388.  
  389.   SHA1_Init(&context);
  390.   
  391.   dummy = buff[0] & 0x3f;
  392.  
  393.   if(dummy == PT_SUBSECKEY)
  394.     dummy = PT_SECKEY;
  395.   if(dummy == PT_SUBKEY)
  396.     dummy = PT_PUBKEY;
  397.   
  398.   dummy = (buff[0] & 0xb0) | (dummy << 2) | 0x01; 
  399.   SHA1_Update(&context, &dummy, 1);
  400.   dummy = ((l - 1) >> 8) & 0xff;
  401.   SHA1_Update(&context, &dummy, 1);
  402.   dummy = (l - 1) & 0xff; 
  403.   SHA1_Update(&context, &dummy, 1);
  404.   SHA1_Update(&context, buff + 1, l - 1);
  405.   SHA1_Final(digest, &context);
  406.  
  407. }
  408.  
  409. static KEYINFO *pgp_parse_pgp3_key(unsigned char *buff, size_t l)
  410. {
  411.   KEYINFO *p;
  412.   unsigned char alg;
  413.   unsigned char digest[SHA_DIGEST_LENGTH];
  414.   unsigned char scratch[LONG_STRING];
  415.   unsigned long gen_time = 0;
  416.   long id;
  417.   int i, k;
  418.   short len;
  419.   size_t j;
  420.   
  421.   p = pgp_new_keyinfo();
  422.   j = 2;
  423.   
  424.   for(i = 0; i < 4; i++)
  425.     gen_time = (gen_time << 8) + buff[j++];
  426.  
  427.   p->gen_time = gen_time;
  428.   
  429.   alg = buff[j++];
  430.   
  431.   p->algorithm = pkalgbytype(alg);
  432.   p->flags |= get_abilities(alg);
  433.  
  434.   pgp_make_pgp3_fingerprint(buff, l, digest);
  435.   
  436.   for(k = 0; k < 2; k++)
  437.   {
  438.     for(id = 0, i = SHA_DIGEST_LENGTH - 8 + k*4; i < SHA_DIGEST_LENGTH; i++)
  439.       id = (id << 8) + digest[i];
  440.   
  441.     snprintf((char *)scratch + k * 8,